home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / ugly / fname.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  11.6 KB  |  503 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1993-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * ugly/fname.c - filename processing functions
  22.  *
  23.  * updated: 22-Sep-1997
  24.  * created: 24-May-1994
  25.  *
  26.  *-------------------------------------------------------------------
  27.  *
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33.  
  34. #include "utypes.h"
  35. #include "umemory.h"
  36. #include "ustring.h"
  37. #include "expstr.h"
  38.  
  39. #define NOEXTERN_UGLY_FNAME_H
  40. #include "fname.h"
  41.  
  42. /*
  43.  * get_fext
  44.  *
  45.  * get filename extension
  46.  *
  47.  * params: fn...full filename to examine
  48.  * result: extension of _fn or NULL, if fn was also NULL
  49.  *
  50.  */
  51. BOOL get_fext(EXPSTR * dest, CONSTRPTR fn)
  52. {
  53.     CONSTRPTR fn_ext = fn;      /* result var */
  54.  
  55.     /* search for end of string */
  56.     while (fn_ext[0])
  57.         fn_ext++;
  58.  
  59.     /* search string backwards for "." or PATH_SEPARATOR */
  60.     do
  61.         /* nufin */ ;
  62.     while ((fn_ext != fn)       /* beginning of name reached? */
  63.            && (fn_ext--)        /* process next char */
  64.            && (fn_ext[0] != '.')
  65.            && (strchr(PATH_SEPARATOR, fn_ext[0]) == NULL));
  66.  
  67.     /* copy extension to dest */
  68.     if (fn_ext[0] == '.')
  69.         set_estr(dest, ++fn_ext);
  70.     else
  71.         clr_estr(dest);
  72.  
  73.     return (ok_fnl_fext(dest));
  74. }
  75.  
  76. /*
  77.  * get_fname
  78.  *
  79.  *
  80.  */
  81. BOOL get_fname(EXPSTR * dest, CONSTRPTR fn)
  82. {
  83.     CONSTRPTR fn_name = fn;
  84.  
  85.     fn_name = ustrrpbrk(fn_name, PATH_SEPARATOR);
  86.  
  87.     /* copy extension to dest */
  88.     if (fn_name)
  89.         set_estr(dest, ++fn_name);
  90.     else
  91.         set_estr(dest, fn);
  92.  
  93.     return (ok_fnl_fname(dest));
  94. }
  95.  
  96. /*
  97.  * get_fpath
  98.  *
  99.  *
  100.  */
  101. BOOL get_fpath(EXPSTR * dest, CONSTRPTR fn)
  102. {
  103.     STRPTR pa_name = ustrrpbrk(fn, PATH_SEPARATOR);
  104.  
  105.     if (pa_name)
  106.     {
  107.         set_estrn(dest, fn, strlen(fn) - strlen(pa_name) + 1);
  108.     }
  109.     else
  110.         clr_estr(dest);
  111.  
  112.     return (ok_fnl_fpath(dest));
  113. }
  114.  
  115. /*
  116.  * get_fsdir: get next subdirectory (including separator)
  117.  *
  118.  */
  119. BOOL get_fsdir(EXPSTR * dest, CONSTRPTR fn)
  120. {
  121.     STRPTR fn_name = strpbrk(fn, PATH_SEPARATOR);
  122.  
  123.     if (fn_name)
  124.     {
  125.         set_estrn(dest, fn, strlen(fn) - strlen(fn_name) + 1);
  126.     }
  127.     else
  128.         clr_estr(dest);
  129.  
  130.     return (ok_fnl_fpath(dest));
  131. }
  132.  
  133. /*
  134.  * get_fdrive
  135.  *
  136.  *
  137.  */
  138. BOOL get_fdrive(EXPSTR * dest, CONSTRPTR fn)
  139. {
  140.     set_estr(dest, fn);         /* dummy data */
  141.     clr_estr(dest);
  142.     return (ok_fnl_fpath(dest));
  143. }
  144.  
  145. /*
  146.  * fextidx: get filename extension index of string
  147.  *
  148.  * params: fn...filename to examine
  149.  * result: index in _fn, where extension starts
  150.  *
  151.  * NOTE: if _fn has an extension at all, _fn[i] is equal to '.', else
  152.  *       _fn has no extension (e.g. "TESTFILE") and _fn[i] is equal
  153.  *       to '\0'.
  154.  *
  155.  * (internal function)
  156.  *
  157.  */
  158. static size_t fextidx(CONSTRPTR fn)
  159. {
  160.     size_t i;                   /* string index counter */
  161.  
  162.     i = strlen(fn) - 1;         /* scan string backwards... */
  163.     while ((i) && (fn[i] != '.')
  164.            && (strchr(PATH_SEPARATOR, fn[i]) == NULL))
  165.         i--;
  166.     if (fn[i] != '.')
  167.         i = strlen(fn);
  168.  
  169.     return i;                   /* return result */
  170. }
  171.  
  172. /*
  173.  * clr_fext: clear filename extension
  174.  *
  175.  * params: dest...string that contains filename to strip
  176.  *
  177.  * EXAMPLE: "testfile.txt" -> "testfile"
  178.  *
  179.  */
  180. BOOL clr_fext(EXPSTR * dest)
  181. {
  182.     BOOL ok;
  183.     size_t extidx = fextidx(estr2str(dest));
  184.     /* index, where extension starts */
  185.     ok = set_estrn(dest, estr2str(dest), extidx);
  186.     ok &= ok_fnl_fpath(dest);
  187.  
  188.     return (ok);
  189. }
  190.  
  191. /*
  192.  * set_fext: set new (last) extension for filename
  193.  *
  194.  * params: dest....string that contains old filename
  195.  *         newext..new extension to set
  196.  *
  197.  * EXAMPLE: "testfile.txt", "lha" -> "testfile.lha"
  198.  *          "hugo.tar.gz" , "lha" -> "hugo.tar.lha"
  199.  */
  200. BOOL set_fext(EXPSTR * dest, CONSTRPTR newext)
  201. {
  202.     BOOL ok;
  203.  
  204.     ok = clr_fext(dest);
  205.     ok &= app_estrch(dest, '.');
  206.     ok &= app_estr(dest, newext);
  207.  
  208.     ok &= ok_fnl_fpath(dest);
  209.  
  210.     return (ok);
  211. }
  212.  
  213. /*
  214.  * app_fext: append extension to filename
  215.  *
  216.  * EXAMPLE: ("testfile.txt", "lha") -> "testfile.txt.lha"
  217.  *                                  -> "testfile.lha"     (msdos)
  218.  */
  219. BOOL app_fext(EXPSTR * dest, CONSTRPTR newext)
  220. {
  221.     BOOL ok = app_estrch(dest, '.');
  222.  
  223.     ok &= app_estr(dest, newext);
  224.     ok &= ok_fnl_fpath(dest);
  225.  
  226.     return (ok);
  227. }
  228.  
  229. /*
  230.  * set_fextIdx: set file name index extension
  231.  *
  232.  * params: dest..destination string with new extension
  233.  *         fn....source string with extension to replace
  234.  *         idx...extension index
  235.  */
  236. BOOL set_fnameIdx(EXPSTR * dest, int idx)
  237. {
  238.     char fn_ext[12];            /* index extension */
  239.     sprintf(fn_ext, "%03d", idx);       /* create index string */
  240.  
  241.     return (set_fext(dest, fn_ext));
  242. }
  243.  
  244. /*
  245.  * link_fname: link directory and filename together
  246.  *
  247.  * params: dest..where to store result
  248.  *         dir...directoryname
  249.  *         fn....filename to append
  250.  *
  251.  * NOTE: a PATHSEPARATOR[0] is append to dir, if none exists
  252.  * NOTE: dir and fn MUST NOT be part of dest,
  253.  *       when invoking this funtion
  254.  */
  255. BOOL link_fname(EXPSTR * dest, STRPTR dir, STRPTR fn)
  256. {
  257.     BOOL anydir;                /* TRUE, if any dir passed as arg */
  258.     BOOL ok = TRUE;
  259.  
  260.     /* is a dir passed? */
  261.     anydir = (dir != NULL);
  262.     if (anydir)
  263.         anydir = (strlen(dir) != 0);
  264.  
  265.     if (anydir)
  266.     {
  267.         /* clone dir, if any
  268.          *
  269.          * NOTE: it's neccesarry to work with a copy do `dir',
  270.          * because if `dir' is part or `dest', this could lead
  271.          * to a mungwall hit */
  272.         STRPTR dir_clone = strclone(dir);       /* clone of `dir' */
  273.  
  274.         set_estr(dest, dir_clone);
  275.         /* check, if the last char of dir is a path separator */
  276.         /* ->if not, append a direcory separator */
  277.         if (!strchr(PATH_SEPARATOR, dir_clone[strlen(dir_clone) - 1]))
  278.             app_estrch(dest, DIR_SEPARATOR);
  279.  
  280.         /* free cloned dir */
  281.         ufreestr(dir_clone);
  282.     }
  283.     else
  284.         clr_estr(dest);
  285.  
  286.     /* append filename */
  287.     if (fn)
  288.         app_estr(dest, fn);
  289.  
  290.     ok &= ok_fnl_fpath(dest);
  291.  
  292.     return ok;
  293. }
  294.  
  295. /*
  296.  * link_envfname: link content of an environment variable,
  297.  *                directory and filename together
  298.  *
  299.  * params: dest..where to store result
  300.  *         env...name of environment variable
  301.  *         dir...directoryname
  302.  *         fn....filename to append
  303.  *
  304.  * result: FALSE, if envvar could not be found or
  305.  *         filename got too long
  306.  */
  307. BOOL link_envfname(EXPSTR * dest, STRPTR envname, STRPTR dir, STRPTR fn)
  308. {
  309.     BOOL ok = FALSE;
  310.     STRPTR env = getenv(envname);
  311.  
  312.     if (env)
  313.     {
  314.         STRPTR env1 = strclone(env);        /* copy envvar to own memory area */
  315.         EXPSTR *tmpstr = init_estr(32);
  316.  
  317.         /* strip linefeeds from hscenv */
  318.         while (strlen(env1) && (env1[strlen(env1)] == '\n'))
  319.             env1[strlen(env1)] = '\0';
  320.  
  321.         if (dir)
  322.         {
  323.             link_fname(tmpstr, env1, dir);
  324.         }
  325.         else
  326.         {
  327.             set_estr(tmpstr, env1);
  328.         }
  329.  
  330.         ok = link_fname(dest, estr2str(tmpstr), fn);
  331.  
  332.         del_estr(tmpstr);
  333.         ufreestr(env1);
  334.     }
  335.     else
  336.     {
  337.         clr_estr(dest);
  338.     }
  339.  
  340.     return ok;
  341. }
  342.  
  343. /*
  344.  * tmpnamstr: alloc & create a string with a temp. filename
  345.  *
  346.  * result: string containig filename;
  347.  *         MUST be release using ufreestr() by caller
  348.  * errors: return NULL; this can be because auf no more
  349.  *         temp. files available or out of mem
  350.  *
  351.  * IMPORTANT: you need to copy the filename, if you
  352.  *           call this function frquently
  353.  */
  354. static size_t adjust_prefixlen(size_t prefixlen)
  355. {
  356. #ifdef MSDOS
  357.     if (prefixlen > MAX_FNAME - 4)
  358.         prefixlen = MAX_FNAME - 4;
  359. #else
  360.     if (prefixlen > MAX_FNAME - 8)
  361.         prefixlen = MAX_FNAME - 8;
  362. #endif
  363.  
  364.     return (prefixlen);
  365. }
  366.  
  367. STRPTR tmpnamstr(STRPTR prefix)
  368. {
  369.     static LONG fileidx = 0;
  370.     STRARR buf[256 + 32];
  371.     STRPTR s = NULL;
  372.     FILE *file = NULL;
  373.     size_t prefixlen = 0;
  374.  
  375.     if (prefix)
  376.         /* copy prefix to buffer */
  377.         prefixlen = adjust_prefixlen(strlen(prefix));
  378.     else
  379.         prefix = "";
  380.  
  381.     /* copy prefix to buffer */
  382.     strcpy(buf, prefix);
  383.  
  384.     /* add address of buffer to prefix */
  385.     sprintf(&(buf[strlen(prefix)]), "%p", tmpnamstr);
  386.  
  387.     prefixlen = adjust_prefixlen(strlen(buf));
  388.     buf[prefixlen] = '\0';
  389.  
  390.     /* try to open tmpfile for input until it fails */
  391.     do
  392.     {
  393.         fileidx++;
  394.         sprintf(&(buf[prefixlen]), "%04lx", fileidx);
  395.         strcat(buf, ".tmp");
  396.         file = fopen(buf, "r");
  397.         if (file)
  398.         {
  399.             fclose(file);
  400.             if (fileidx == 0xffff)
  401.                 fileidx = 0;    /* ran out of names */
  402.         }
  403.     }
  404.     while (fileidx && file);
  405.  
  406.     if (fileidx)
  407.     {
  408.         s = buf;
  409.     }
  410.  
  411.     return (s);
  412. }
  413.  
  414. /*
  415.  * get_relfname: get relative filename, according to given path
  416.  *
  417.  * params: absn..absolute filename
  418.  *         curp..current path
  419.  *
  420.  * EXAMPLE:
  421.  *  "image/back.gif" and "image/hugo/" -> "/back.gif"
  422.  *  "image/back.gif" and ""            -> "image/back.gif"
  423.  *  "image/back.gif" and "people/"     -> "/image/back.gif"
  424.  */
  425. BOOL get_relfname(EXPSTR * dest, STRPTR absn, STRPTR curp)
  426. {
  427.     EXPSTR *fname = init_estr(32);      /* file name only */
  428.     EXPSTR *abspa = init_estr(32);      /* absolute path only */
  429.     EXPSTR *tmpp1 = init_estr(32);      /* temp pointer */
  430.     EXPSTR *tmpp2 = init_estr(32);
  431.     STRPTR rest_absp = NULL;    /* rest of current path */
  432.     STRPTR absp = NULL;         /* path processing */
  433.     int cmp_result;             /* stores result returned by upstrcmp */
  434.  
  435.     /* init string array */
  436.     clr_estr(dest);
  437.     get_fname(fname, absn);
  438.     get_fpath(abspa, absn);
  439.     absp = estr2str(abspa);
  440.  
  441.     /*
  442.      * skip all equal subdirs
  443.      */
  444.     do
  445.     {
  446.         get_fsdir(tmpp1, absp);
  447.         get_fsdir(tmpp2, curp);
  448.         cmp_result = upstrcmp(estr2str(tmpp1), estr2str(tmpp2));
  449.  
  450.         if (!cmp_result)
  451.         {
  452.             absp += estrlen(tmpp1);
  453.             curp += estrlen(tmpp2);
  454.         }
  455.     }
  456.     while (estrlen(tmpp1)
  457.            && estrlen(tmpp2)
  458.            && (!cmp_result));
  459.  
  460.     /* remember equal part of path */
  461.     rest_absp = absp;
  462.  
  463.     /*
  464.      * for every subdir in absp unequal to
  465.      * corresponding subdir curp, insert a parent dir
  466.      */
  467.     if (curp[0])
  468.         do
  469.         {
  470.             get_fsdir(tmpp1, absp);
  471.             get_fsdir(tmpp2, curp);
  472.             cmp_result = upstrcmp(estr2str(tmpp1), estr2str(tmpp2));
  473.  
  474.             if (cmp_result)
  475.             {
  476.                 absp += estrlen(tmpp1);
  477.                 curp += estrlen(tmpp2);
  478.                 app_estr(dest, PARENT_DIR);
  479. #if 0
  480.                 printf("absp: (tmpp1) [%d] `%s'\n", estrlen(tmpp1), absp);
  481.                 printf("curp: (tmpp2) [%d] `%s'\n", estrlen(tmpp2), curp);
  482.                 printf("dest: `%s'\n", estr2str(dest));
  483. #endif
  484.             }
  485.         }
  486.         while (strlen(curp) && cmp_result);
  487.  
  488.     /* append equal part of path */
  489.     app_estr(dest, rest_absp);
  490.  
  491.     /* append name of file */
  492.     app_estr(dest, estr2str(fname));
  493.  
  494.     /* relaese resources */
  495.     del_estr(fname);
  496.     del_estr(abspa);
  497.     del_estr(tmpp1);
  498.     del_estr(tmpp2);
  499.  
  500.     return (ok_fnl_fpath(dest));
  501. }
  502.  
  503.